


import java.util.Hashtable;

import omicronAPI.*;

import processing.core.*;
import com.modestmaps.*;
import com.modestmaps.core.*;
import com.modestmaps.geo.*;
import com.modestmaps.providers.*;

//import org.apache.log4j.Logger;

public class TouchMap {
	PApplet parent = null;

	public InteractiveMap map;

	public float borderx1 = 0;
	public float borderx2 = 0;
	public float bordery1 = 0;
	public float bordery2 = 0;
	float anchorPositionx = 0;
	float anchorPositiony = 0;
	int scaleFactor = 1;
	boolean isModest = false;
	Point2f mouseLoc = null;
	Hashtable touchList;
	Location locationUSA;
	
	PVector lastTouchPos;
	PVector lastTouchPos2;
	int touchID1;
	int touchID2;

	PVector initTouchPos;
	PVector initTouchPos2;
	
	public TouchMap(PApplet parent, int scaleFactor){
		locationUSA = new Location(38.962f, -93.928f); // Use with zoom level 6
		lastTouchPos = new PVector();
		lastTouchPos2 = new PVector();
		initTouchPos = new PVector();
		initTouchPos2 = new PVector();
		PVector initTouchPos = new PVector();
		PVector initTouchPos2 = new PVector();
		
		
		
		this.parent = parent;
		borderx1 = parent.width*0.75f;
		borderx2 = parent.width;
	    bordery1 = 50*scaleFactor;
	    bordery2 = parent.height-(50*scaleFactor);
	    map = new InteractiveMap(parent, new Microsoft.RoadProvider(), borderx1, bordery1, borderx2-borderx1, bordery2-bordery1 );
	    //mapModest.locationPoint(new Location(39.93f, -93.45f));
	    //map.setPanningRestriction(new Location(39.93f, -93.45f), 300);
	    mouseLoc = new Point2f(0,0);
	    this.scaleFactor = scaleFactor;
	    //map.setScaleRange(3, 14);
	    //MouseHandler handler = new MouseHandler(this.parent, map);
	    map.setCenterZoom(locationUSA, 4);  
	        
	    // Show map around the location in the given zoom level.
	   
	    //map.setZoom(4);
	    //map.zoomAndPanTo(new Location(41.6f, -87.9f), 8);
	    //map.zoomAndPanTo(new Location(41.6f, -87.9f), 13);
	    touchList = new Hashtable();
	    

	}
	
	public float getWidth(){
		return borderx2-borderx1;
	}
	
	public float getHeight(){
		return bordery2-bordery1;
	}
	
	public float getOffsetX(){
		return borderx1;
	}
	
	public float getOffsetY(){
		return bordery1;
	}
	
	public Point2f getPosByCoord(float lat, float longit){
		return map.locationPoint(new Location(lat, longit));
	}
	public int getZoomLevel(){
		return map.getZoom();
	}
	
	public boolean isMapTouch(float xPos, float yPos){
		return borderx1 >= xPos && xPos <= borderx2 && bordery1 <= yPos && bordery2 >= yPos;
	}
	
	
	public void draw(){
		map.draw();
		mouseLoc.x = parent.mouseX;
		mouseLoc.y = parent.mouseY;
		Location location = map.pointLocation(mouseLoc);
	    parent.fill(0);
	    parent.text(location.lat + ", " + location.lon, parent.mouseX, parent.mouseY);
	    
	    // draw window borders
	    parent.fill(170);
	    //parent.strokeWeight(4);
	    //parent.stroke(45);
	    parent.stroke(170);
	    parent.strokeWeight(0);
	    parent.rect(0, 0, borderx1, parent.height);
	    parent.rect(borderx1, 0, parent.width, bordery1);
	    parent.rect(borderx1,parent.height-(50*scaleFactor),parent.width,parent.height);
	    parent.strokeWeight(1);
	    parent.stroke(0);
	    parent.noFill();
	    parent.rect(borderx1,bordery1,borderx2,bordery2);
	    parent.fill(170);
	    
	
	    
	}
	
	

	
	void touchDown(int ID, float xPos, float yPos, float xWidth, float yWidth) {
		  // Update the last touch position
		  lastTouchPos.x = xPos;
		  lastTouchPos.y = yPos;
		  
		  // Add a new touch ID to the list
		Point2f t = new Point2f(xPos, yPos);
		touchList.put(ID,t);
		

		  if( touchList.size() == 1 ){ // If one touch record initial position (for dragging). Saving ID 1 for later
		    touchID1 = ID;
		    initTouchPos.x = xPos;
		    initTouchPos.y = yPos;
		  }
		  else if( touchList.size() == 2 ){ // If second touch record initial position (for zooming). Saving ID 2 for later
		    touchID2 = ID;
		    initTouchPos2.x = xPos;
		    initTouchPos2.y = yPos;
		  }
		
		
	}// touchDown

	
	
	void touchMove(int ID, float xPos, float yPos, float xWidth, float yWidth) {
		if( touchList.size() < 2 ){
		    // Only one touch, drag map based on last position
		    map.tx += (xPos - lastTouchPos.x)/map.sc;
		    map.ty += (yPos - lastTouchPos.y)/map.sc;
		  } else if( touchList.size() == 2 ){
		    // Only two touch, scale map based on midpoint and distance from initial touch positions
		    
		    float sc = parent.dist(lastTouchPos.x, lastTouchPos.y, lastTouchPos2.x, lastTouchPos2.y);
		    float initPos = parent.dist(initTouchPos.x, initTouchPos.y, initTouchPos2.x, initTouchPos2.y);
		    
		    PVector midpoint = new PVector( (lastTouchPos.x+lastTouchPos2.x)/2, (lastTouchPos.y+lastTouchPos2.y)/2 );
		    sc -= initPos*.85f;
		    sc /= 5000;
		    sc += 1;
		    //println(sc);
		    float mx = (midpoint.x - getOffsetX()) - getWidth()/2;
		    float my = (midpoint.y - getOffsetY()) - getHeight()/2;
		    map.tx -= mx/map.sc;
		    map.ty -= my/map.sc;
		    map.sc *= sc;
		    map.tx += mx/map.sc;
		    map.ty += my/map.sc;
		  } else if( touchList.size() >= 5 ){
		    
		    // Zoom to entire USA
		    map.setCenterZoom(locationUSA, 6);  
		  }
		  
		  // Update touch IDs 1 and 2
		  if( ID == touchID1 ){
		    lastTouchPos.x = xPos;
		    lastTouchPos.y = yPos;
		  } else if( ID == touchID2 ){
		    lastTouchPos2.x = xPos;
		    lastTouchPos2.y = yPos;
		  } 
		  
		  // Update touch list
		  Point2f t = new Point2f(xPos, yPos);
		  touchList.put(ID,t);

	}// touchMove

	void touchUp(int ID, float xPos, float yPos, float xWidth, float yWidth) {
		touchList.remove(ID);
	}// touchUp
	
	public void zoomIn(){
		map.zoomIn();
	}
	public void zoomOut(){
		map.zoomOut();
	}
	public void SetProvider(MapType provider){
		map.setMapProvider(provider.provider());
	}

}
